#!/usr/bin/env python

# (c) 2007-2011 Helsinki University of Technology and University of Helsinki
# Licensed under the MIT license; see LICENSE.txt for more information.

from rdflib import Namespace, URIRef, Literal, BNode, RDF, RDFS
try:			# rdflib 2.4.x
  from rdflib.Graph import Graph
  from rdflib.Literal import _XSD_NS as XSD_NS
except ImportError:	# rdflib 3.0.0
  from rdflib import Graph
  from rdflib import XSD as XSD_NS
from rdflib.exceptions import UniquenessError
from threading import Lock

USE_SLEEPYCAT = False

# formats to parse
RDF_FORMATS = ('xml', 'n3', 'nt', 'rdfa')

DC = Namespace("http://purl.org/dc/elements/1.1/")
DCTERMS = Namespace("http://purl.org/dc/terms/")
DCMITYPE = Namespace("http://purl.org/dc/dcmitype/")
TS = Namespace("http://www.yso.fi/onto/tervesuomi-schema/")
TOSU = Namespace("http://www.yso.fi/onto/toimintasuomi-schema/")
GENRE = Namespace("http://www.yso.fi/onto/tervesuomi-genre/")
AUDIENCE = Namespace("http://www.yso.fi/onto/audience/")
SECTION = Namespace("http://www.yso.fi/onto/tervesuomi-section/")
TERO = Namespace("http://www.yso.fi/onto/tero/")
EVENTTYPE = Namespace("http://www.yso.fi/onto/tosu-eventtype/")
FOAF = Namespace("http://xmlns.com/foaf/0.1/")
AGENT = Namespace("http://demo.seco.tkk.fi/tervesuomi/agent/")
SKOS = Namespace("http://www.w3.org/2004/02/skos/core#")
SKOSEXT = Namespace("http://www.w3.org/2004/02/skos/extensions#")
SKOSMAP = Namespace("http://www.w3.org/2004/02/skos/mapping#")
IANAMIME = Namespace("http://www.yso.fi/onto/ianamime/")
SAHA3 = Namespace("http://seco.tkk.fi/saha3/")
ICAL = Namespace("http://www.w3.org/2002/12/cal/icaltzd#")
ICALOLD = Namespace("http://www.w3.org/2002/12/cal/ical#")
VCARD = Namespace("http://www.w3.org/2006/vcard/ns#")
AGRICOLA = Namespace("http://www.yso.fi/onto/agricola.utu.fi#")
MUSEUM = Namespace("http://www.yso.fi/onto/www.museot.fi#")
TIME = Namespace("http://www.yso.fi/onto/time-schema#")
EVENT = Namespace("http://schema.onki.fi/event#")
LODE = Namespace("http://linkedevents.org/ontology/")
OWL = Namespace("http://www.w3.org/2002/07/owl#")

METADATA_FIELDS = {
  TS.Publication: (
    ('Identifier', 'dc:identifier', DC.identifier),
    ('URL address', 'ts:url', TS.url),
    ('Title', 'dc:title', DC['title']),
    ('Description', 'dc:description', DC['description']),
    ('Language', 'dc:language', DC.language),
    ('Date issued', 'dcterms:issued', DCTERMS.issued),
    ('Date accepted', 'dcterms:dateAccepted', DCTERMS.dateAccepted),
    ('Date modified', 'dcterms:modified', DCTERMS.modified),
    ('Publisher', 'dc:publisher', DC.publisher),
    ('Creator', 'dc:creator', DC.creator),
    ('Publication type', 'ts:genre', TS.genre),
    ('Type', 'dc:type', DC.type),
    ('Format', 'dc:format', DC['format']),
    ('Subject', 'dc:subject', DC.subject),
    ('Keyword', 'ts:keyword', TS.keyword),
    ('Audience', 'dcterms:audience', DCTERMS.audience),
    ('Rights', 'dc:rights', DC.rights),
  ),
  ICAL.Vevent: (
    ('Summary', 'ical:summary', ICAL.summary),
    ('Description', 'ical:description', ICAL.description),
    ('Start time', 'ical:dtstart', ICAL.dtstart),
    ('End time', 'ical:dtend', ICAL.dtend),
    ('Available date', 'tosu:available', TOSU.available),
    ('Expiration date', 'tosu:expires', TOSU.expires),
    ('Registration deadline', 'tosu:registrationDeadline', TOSU.registrationDeadline),
    ('Location', 'ical:location', ICAL.location),
    ('Organizer', 'ical:organizer', ICAL.organizer),
    ('Publisher', 'dcterms:publisher', DCTERMS.publisher),
    ('Creator', 'dcterms:creator', DCTERMS.creator),
    ('Event type', 'tosu:eventType', TOSU.eventType),
    ('Subject', 'dcterms:subject', DCTERMS.subject),
    ('Keyword', 'tosu:keyword', TOSU.keyword),
    ('Goal', 'tosu:goal', TOSU.goal),
    ('Target audience', 'dcterms:audience', DCTERMS.audience),
    ('Entry fee', 'tosu:fee', TOSU.fee),
    ('Registration required', 'tosu:registrationRequired', TOSU.registrationRequired),
    ('Image', 'tosu:image', TOSU.image),
    ('URL address', 'ical:url', ICAL.url),
  ),
  EVENT.Event: (
    ('Summary', 'ical:summary', ICAL.summary),
    ('Description', 'ical:description', ICAL.description),
    ('Start time', 'ical:dtstart', ICAL.dtstart),
    ('End time', 'ical:dtend', ICAL.dtend),
    ('Location', 'ical:location', ICAL.location),
    ('Organizer', 'ical:organizer', ICAL.organizer),
    ('Publisher', 'dcterms:publisher', DCTERMS.publisher),
    ('Creator', 'dcterms:creator', DCTERMS.creator),
    ('Subject', 'dcterms:subject', DCTERMS.subject),
    ('Target audience', 'dcterms:audience', DCTERMS.audience),
    ('Entry fee', 'event:fee', EVENT.fee),
    ('URL address', 'ical:url', ICAL.url),
  ),
  LODE.Event: (
    ('Title', 'dc:title', DC.title),
    ('Description', 'dc:description', DC.description),
    ('Time', 'ical:dtstart', ICAL.dtstart),
    ('Space', 'ical:location', ICAL.location),
    ('Subject', 'dcterms:subject', DCTERMS.subject),
#    ('URL address', 'owl:sameAs', OWL.sameAs),
  ),
  TOSU.VoluntaryWork: (
    ('Title', 'dct:title', DCTERMS['title']),
    ('Description', 'dct:description', DCTERMS.description),
    ('Content', 'tosu:content', TOSU.content),
    ('Spatial coverage', 'dct:spatial', DCTERMS.spatial),
    ('Time', 'tosu:time', TOSU.time),
    ('Action type (keyword)', 'tosu:actionType', TOSU.actionType),
    ('Activity', 'tosu:activity', TOSU.activity),
    ('Work time', 'tosu:workTime', TOSU.workTime),
    ('Key factor', 'tosu:keyFactor', TOSU.keyFactor),
    ('Theme or subject', 'dct:subject', DCTERMS.subject),
    ('Activity target group', 'tosu:targetGroup', TOSU.target),
    ('Representative', 'tosu:representative', TOSU.representative),
    ('Organizer', 'tosu:organizer', TOSU.organizer),
    ('Language', 'dct:language', DCTERMS.language),
  ),
}

RECOGNIZED_RDF_TYPES = (
  TS.Publication,
  ICAL.Vevent,
  ICALOLD.Vevent,
  AGRICOLA.Event,
  MUSEUM.Event,
  EVENT.Event,
  LODE.Event,
  TOSU.VoluntaryWork,
)

class MetadataGraph (Graph):
  def __init__(self, name):
    if USE_SLEEPYCAT:
      Graph.__init__(self, 'Sleepycat')
      self.open('/tmp/' + name, True) # FIXME
    else:
      Graph.__init__(self)
    self.namespace_manager.bind('dc', DC)
    self.namespace_manager.bind('dcterms', DCTERMS)
    self.namespace_manager.bind('dcmitype', DCMITYPE)
    self.namespace_manager.bind('skos', SKOS)
    self.namespace_manager.bind('ical', ICAL)
    self.namespace_manager.bind('vcard', VCARD)
    self.namespace_manager.bind('ts', TS)
    self.namespace_manager.bind('tosu', TOSU)
    self.namespace_manager.bind('genre', GENRE)
    self.namespace_manager.bind('foaf', FOAF)
    self.namespace_manager.bind('event', EVENT)
    self.namespace_manager.bind('owl', OWL)


# it appears that rdflib's BNode constructor is not thread-safe, so wrap it with locks
# the BNode constructor is also used by Graph, so that has to be wrapped as well
bnodeLock = Lock()

def getBNode():
  bnodeLock.acquire()
  bnode = BNode()
  bnodeLock.release()
  return bnode

def getGraph():
  bnodeLock.acquire()
  graph = Graph()
  bnodeLock.release()
  return graph

def getMetadataGraph(name):
  bnodeLock.acquire()
  graph = MetadataGraph(name)
  bnodeLock.release()
  return graph
  
